using System;
using System.Collections;
using System.Data;
using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls;
using PHSRAG.Insight21.Common.Pages;
using PHSRAG.Insight21.Context;
using PHSRAG.Insight21.InsightWebControls;
using PHSRAG.Insight21.Personnel;
using PHSRAG.Insight21.Policy;
using PHSRAG.Insight21.SearchContext;
using PHSRAG.Utility;
using Constants=PHSRAG.Insight21.InsightUtilities.Constants;
using Distribution = PHSRAG.Insight21.Personnel.MonthlyLaborDistribution;
using PersonnelConstants = PHSRAG.Insight21.Personnel.Constants;

namespace PHSRAG.Insight21
{
    /// <summary>
    /// Summary description for MonthlyLaborDistributions.
    /// </summary>
    public partial class MonthlyLaborDistribution : NoCachePage
    {
        #region Constants

        private const string CurrentDetailEndDateKey = "CurrentDetailEndMonth_21D58C0E-C5BA-4581-AB9A-45F097A67BD6";
        private const string DeficitStyleName = "deficit";
        private const string ExcelReportControlFilePath = "../../Personnel/Reports/MonthlyLaborDistributionExcel.ascx";
        private const string SearchCriteriaVersionKey = "SearchCriteriaVersion_21D58C0E-C5BA-4581-AB9A-45F097A67BD6";

        #endregion

        #region Instance variables (Private)

        private ICachePolicy cachePolicy;
        private ICachePolicy pageCachePolicy;

        #endregion

        #region Private Properties

        /// <summary>
        /// Get/Set the current Detail end date within the datagrid for display. This information persists across page loads.
        /// This information is cached using the page cache policy
        /// Get: Return the value from the page cache policy, returns 0 if its not present in cache
        /// Set: Set the value and update the cache
        /// </summary>
        private DateTime CurrentDetailEndDate
        {
            get
            {
                Hashtable h = pageCachePolicy.GetCachedObject(Keys.MonthlyLaborDistributionPageKey) as Hashtable;
                return (h == null || h[CurrentDetailEndDateKey] == null) ? DateTime.Today : (DateTime) h[CurrentDetailEndDateKey];
            }
            set
            {
                Hashtable h = pageCachePolicy.GetCachedObject(Keys.MonthlyLaborDistributionPageKey) as Hashtable ?? new Hashtable();
                h[CurrentDetailEndDateKey] = value;
                pageCachePolicy.Cache(Keys.MonthlyLaborDistributionPageKey, h);
            }
        }

        /// <summary>
        /// Get the labor distribution informations that the logged-in user has access to. The list of distributions is
        /// is maintained by the LabourDistributions business object within its data container. This object is cached.
        /// The LaborDistributions instance is loaded based on from where the user is navigating to this page.
        /// Everytime the page is loaded for the firsttime the LaborDistributions instance will be reloaded.
        /// </summary>
        private MonthlyLaborDistributions MonthlyLaborDistributions
        {
            get
            {
                CommonSearchContext searchContext = (CommonSearchContext) cachePolicy.GetCachedObject(CommonSearchContext.CacheKey);
                SearchCriteria searchCriteria = searchContext.GetSearchCriteria(Page.Request.Url.ToString());
                int searchVersion = searchCriteria.Version;

                //added default values for the search criteriea the first time the page is being loaded.
                if (searchCriteria["PayDateFrom"] == null)
                {
                    //Calculation of PayFromDate has been corrected as per TrackIt 7866    02/19/2008 jml29
                    searchCriteria["PayDateFrom"] = string.Format("10/1/{0}", ((DateTime.Now.Month > 9) ? 0 : -1) + DateTime.Now.Year);
                    searchCriteria["PayDateTo"] = DateTime.Now.ToString("MM/dd/yyyy");
                    searchContext.SetPrimarySearchCriteria(SearchCriteria.Level.Summary, Page.Request.Url.ToString(), "payDateFrom", string.Format("10/1/{0}", ((DateTime.Now.Month > 9) ? 0 : -1) + DateTime.Now.Year), "Pay Date From", CommonSearch.LabelValueSeparator, string.Format("10/1/{0}", ((DateTime.Now.Month > 9) ? 0 : -1) + DateTime.Now.Year));
                    searchContext.SetPrimarySearchCriteria(SearchCriteria.Level.Summary, Page.Request.Url.ToString(), "payDateTo", DateTime.Now.ToString("MM/dd/yyyy"), "Pay Date To", CommonSearch.LabelValueSeparator, DateTime.Now.ToString("MM/dd/yyyy"));
                }

                MonthlyLaborDistributions monthlyLaborDistributions =
                    ResultsCache.GetObject(cachePolicy, MonthlyLaborDistributions.CacheKey) as MonthlyLaborDistributions;

                if ((monthlyLaborDistributions == null) || (searchVersion != SearchCriteriaVersion) ||
                    CurrentDetailEndDate.ToString("MM/dd/yyyy") != monthlyLaborDistributions.DetailEndDate.ToString("MM/dd/yyyy"))
                {
                    UserContext userContext = (UserContext) cachePolicy.GetCachedObject(UserContext.CacheKey);

                    if (monthlyLaborDistributions != null)
                    {
                        ResultsCache.PurgeObject(cachePolicy);
                    }

                    monthlyLaborDistributions = new MonthlyLaborDistributions();
                    monthlyLaborDistributions.Search(searchCriteria, CurrentDetailEndDate.ToString("MM/dd/yyyy"));

                    ResultsCache.SetObject(cachePolicy, MonthlyLaborDistributions.CacheKey, monthlyLaborDistributions);
                    SearchCriteriaVersion = searchVersion;
                }

                return monthlyLaborDistributions;
            }
        }

        /// <summary>
        /// Gets/sets an integer value indicating the search criteria version. 
        /// The version number changes when the search criteria changes.  This signals the page to re-build its
        /// cache.
        /// </summary>
        private int SearchCriteriaVersion
        {
            get
            {
                Hashtable h = pageCachePolicy.GetCachedObject(Keys.MonthlyLaborDistributionPageKey) as Hashtable;
                return (h == null || h[SearchCriteriaVersionKey] == null) ? 0 : (int) h[SearchCriteriaVersionKey];
            }
            set
            {
                Hashtable h = pageCachePolicy.GetCachedObject(Keys.MonthlyLaborDistributionPageKey) as Hashtable ?? new Hashtable();

                h[SearchCriteriaVersionKey] = value;
                pageCachePolicy.Cache(Keys.MonthlyLaborDistributionPageKey, h);
            }
        }

        #endregion

        #region Event Handlers

        /// <summary>
        /// Handler for the event raised when the grid is about to be rendered.
        /// </summary>
        /// <param name="sender">Control which raised the event</param>
        /// <param name="e">Argument associated with the event</param>
        protected void OnLaborDistributionGridPreRender(object sender, EventArgs e)
        {
            CommonSearchContext searchContext = (CommonSearchContext) cachePolicy.GetCachedObject(CommonSearchContext.CacheKey);
            SearchCriteria searchCriteria = searchContext.GetSearchCriteria(Page.Request.Url.ToString());

            DataGridItem distribItem = laborDistributionGrid.Items[0];
            //show all the columns first as the Visibiliy flag is stored in Viewstate and
            //this could hide columns which are supposed to be shown especially while paging thru
            for (int i = 3; i < distribItem.Cells.Count - 1; i++) //exclude the total column
            {
                laborDistributionGrid.Columns[i].Visible = true;
            }
            if (!string.IsNullOrEmpty(searchCriteria["payDateFrom"]))
            {
                DateTime payDateFrom = Convert.ToDateTime(searchCriteria["payDateFrom"]);
                payDateFrom = payDateFrom.AddDays(1 - payDateFrom.Day); //get first day of the month by subtracting the no. of days

                //the third column through the last but one column are the monthly distributions
                for (int i = 3; i < distribItem.Cells.Count - 1; i++) //exclude the total column
                {
                    if (DateTime.Parse(laborDistributionGrid.Columns[i].HeaderText.Replace("/", "/01/")) < payDateFrom)
                    {
                        laborDistributionGrid.Columns[i].Visible = false;
                    }
                    else
                    {
                        break;
                    }
                }
            }
            if (!string.IsNullOrEmpty(searchCriteria["payDateTo"]))
            {
                DateTime payDateTo = Convert.ToDateTime(searchCriteria["payDateTo"]);
                payDateTo = payDateTo.AddDays(1 - payDateTo.Day); //get first day of the month by subtracting the no. of days
                for (int i = distribItem.Cells.Count - 2; i >= 3; --i) //exclude the total column
                {
                    if (DateTime.Parse(laborDistributionGrid.Columns[i].HeaderText.Replace("/", "/01/")) > payDateTo)
                    {
                        laborDistributionGrid.Columns[i].Visible = false;
                    }
                    else
                    {
                        break;
                    }
                }
            }
        }

        /// <summary>
        /// Handler for the event raised when a row in the datagrid is clicked upon.
        /// </summary>
        /// <param name="source">Control which raised the event</param>
        /// <param name="e">Argument associated with the event</param>
        private void OnItemCommand(object source, DataGridCommandEventArgs e)
        {
            if ((e.Item.ItemType == ListItemType.Item) || (e.Item.ItemType == ListItemType.AlternatingItem))
            {
                Hashtable dictionary = new Hashtable();
                //set the person id in the hash table
                dictionary.Add( /*Keys.PersonIdKey*/"PersonIdKey", Convert.ToInt32(e.Item.Cells[0].Text));

                CommonSearchContext searchContext = (CommonSearchContext) cachePolicy.GetCachedObject(CommonSearchContext.CacheKey);
                SearchCriteria searchCriteria = searchContext.GetSearchCriteria(Page.Request.Url.ToString());

                // if fund # available
                string fundNumber = searchCriteria[Constants.FundNumberKey];
                dictionary.Add(Constants.FundNumberKey, fundNumber);

                //initialize start and end date
                string startDate = MonthlyLaborDistributions.TotalsStartDate.ToShortDateString();
                string endDate = MonthlyLaborDistributions.TotalsEndDate.ToShortDateString();

                if (e.CommandName != "SelectTotal")
                {
                    //a cell in the months column was selected
                    for (int i = 0; i <= e.Item.Cells.Count; ++i)
                    {
                        TableCell tableCell = e.Item.Cells[i];
                        if (tableCell.Controls.Count > 0 && tableCell.Controls[0] == e.CommandSource)
                        {
                            string[] dateParts = laborDistributionGrid.Columns[i].HeaderText.Split('/');
                            DateTime columnStartDate = new DateTime(Convert.ToInt32(dateParts[1]), Convert.ToInt32(dateParts[0]), 1);
                            DateTime columnEndDate = new DateTime(Convert.ToInt32(dateParts[1]), Convert.ToInt32(dateParts[0]), columnStartDate.AddMonths(1).AddDays(-1).Day);

                            DateTime totalsStart = Convert.ToDateTime(startDate);
                            DateTime totalsEnd = Convert.ToDateTime(endDate);

                            //make sure that if the start month is a partial month that it gets accurately captured
                            if (totalsStart.Month != columnStartDate.Month ||
                                totalsStart.Year != columnStartDate.Year)
                            {
                                startDate = columnStartDate.ToShortDateString();
                            }

                            //make sure that if the end month is a partial month that it gets accurately captured
                            if (totalsEnd.Month != columnEndDate.Month ||
                                totalsEnd.Year != columnEndDate.Year)
                            {
                                endDate = columnEndDate.ToShortDateString();
                            }

                            break;
                        }
                    }
                }

                dictionary.Add( /*Keys.PayrollMonthKey*/"PayStartDateKey", startDate);
                dictionary.Add( /*Keys.PayrollMonthKey*/"PayEndDateKey", endDate);

                pageCachePolicy.Cache( /*LaborDistributionDetailsKey*/"LaborDistributionDetailsKey", dictionary);
                PurgeCache();
                Response.Redirect(Settings.GetKeyValue("SubNavigation.Personnel.LaborDistributionURL", ""));
            }
        }

        /// <summary>
        /// Handler for event raised while each data grid item is created.
        /// Help in putting the symbol denoting the sort column in the data grid.
        /// If the item being created is the data grid header:
        /// <list type="bullet">
        /// <item><description>Get the sort column and sort order from the LaborDistributions instance in the cache</description></item>
        /// <item><description>Create a Hashtable of column indices, keyed by the sort expression of each column</description></item>
        /// <item><description>Using the hash table add a label with sort symbol to the column on which sort has happened</description></item>
        /// </list>
        /// </summary>
        /// <param name="sender">Control which raised the event</param>
        /// <param name="e">Argument associated with the event</param>
        private void OnItemCreated(object sender, DataGridItemEventArgs e)
        {
            try
            {
                if (e.Item.ItemType == ListItemType.Header)
                {
                    MonthlyLaborDistributions monthlyLaborDistributions = MonthlyLaborDistributions;
                    Label sortSymbol = new Label();
                    sortSymbol.Text = monthlyLaborDistributions.SortAscending ? Constants.SortAscendingText : Constants.SortDescendingText;
                    sortSymbol.Font.Name = Constants.SortSymbolFontName;

                    Hashtable columnMap = new Hashtable();
                    foreach (DataGridColumn column in laborDistributionGrid.Columns)
                    {
                        columnMap[column.SortExpression] = laborDistributionGrid.Columns.IndexOf(column);
                    }

                    string sortColumn = monthlyLaborDistributions.SortColumn;
                    if (columnMap.ContainsKey(sortColumn))
                    {
                        (e.Item.Cells[(int) columnMap[sortColumn]]).Controls.Add(sortSymbol);
                    }
                }
            }
            catch (Exception ex)
            {
                annunciator.Message = Utility.ExceptionReport.GetExceptionInfo(ex, false);
            }
        }

        /// <summary>
        /// Handler for the event raised when a row in the datagrid is databound.
        /// Bind the cells in the Footer with the totals.
        /// </summary>
        /// <param name="sender">Control which raised the event</param>
        /// <param name="e">Argument associated with the event</param>
        private void OnItemDataBound(object sender, DataGridItemEventArgs e)
        {
            try
            {
                DataGridItem distribItem = e.Item;

                if (distribItem.ItemType == ListItemType.Header)
                {
                    DataRow headerRow = MonthlyLaborDistributions.GetDataContainer().
                        Tables[MonthlyLaborDistributions.HeaderDataTableName].Rows[0];
                    //the third column through the last column name come from the header table in the
                    //monthly distribution object's dataset...
                    for (int i = 3; i < distribItem.Cells.Count; i++)
                    {
                        string headerText = headerRow[i - 3].ToString();
                        laborDistributionGrid.Columns[i].HeaderText = headerText;
                        ((LinkButton) distribItem.Cells[i].Controls[0]).Text = headerText;
                    }
                }
                else if (distribItem.ItemType == ListItemType.Item || distribItem.ItemType == ListItemType.AlternatingItem)
                {
                    //the third column through the last column in the collection are money formatted
                    for (int i = 3; i < distribItem.Cells.Count; i++)
                    {
                        TableCell amountCell = distribItem.Cells[i];
                        decimal payAmount = Convert.ToDecimal(((LinkButton) amountCell.Controls[0]).Text);
                        if (payAmount < 0)
                        {
                            ((LinkButton) amountCell.Controls[0]).Text = payAmount.ToString("c");
                            amountCell.CssClass = "DataGridNegativeCurrencyItem";
                        }
                        else if (payAmount == 0)
                        {
                            //no need to link to pay details for the cell
                            string dataValue = ((LinkButton) amountCell.Controls[0]).Text;
                            amountCell.Controls.Clear();
                            amountCell.Controls.Add(new LiteralControl(dataValue));
                        }
                        else
                        {
                            ((LinkButton) amountCell.Controls[0]).Text = payAmount.ToString("c");
                        }
                    }
                }
                else if (distribItem.ItemType == ListItemType.Footer)
                {
                    distribItem.Cells[2].Text = "Total";

                    //the third column the end of the columns collection are money formatted
                    for (int i = 3; i < distribItem.Cells.Count - 1; i++)
                    {
                        string sumExpression = String.Format("sum(Month{0})", Convert.ToString(i - 2));

                        decimal totalAmount = Convert.ToDecimal(MonthlyLaborDistributions.GetDataContainer().
                            Tables[MonthlyLaborDistributions.CurrentDataTableName].
                            Compute(sumExpression, string.Empty));

                        distribItem.Cells[i].Text =
                            string.Format("{0:c}", totalAmount);
                        distribItem.Cells[i].Attributes.Add("align", "right");

                        if (totalAmount < 0)
                        {
                            distribItem.Cells[i].CssClass = "DataGridNegativeCurrencyItem";
                        }
                    }

                    distribItem.Cells[distribItem.Cells.Count - 1].Text =
                        string.Format("{0:c}", MonthlyLaborDistributions.GetDataContainer().
                            Tables[MonthlyLaborDistributions.CurrentDataTableName].
                            Compute("sum(Total)", string.Empty));

                    decimal grandTotal = Convert.ToDecimal(distribItem.Cells.Count - 1);
                    if (grandTotal < 0)
                    {
                        distribItem.Cells[distribItem.Cells.Count - 1].CssClass = "DataGridNegativeCurrencyItem";
                    }

                    distribItem.Cells[distribItem.Cells.Count - 1].CssClass = "footerCell";
                }
            }
            catch (Exception ex)
            {
                annunciator.Message = Utility.ExceptionReport.GetExceptionInfo(ex, false);
            }
        }

        /// <summary>
        /// Handler for the event raised when a column header within the data grid is clicked.
        /// Set the CurrentRecordPageIndex to 0 as sorting need to be done on all records and not only on what is visible
        /// Load the data grid and intialize the pager controls
        /// </summary>
        /// <param name="sender">Control which raised the event</param>
        /// <param name="e">Argument associated with the event</param>
        private void OnSort(object sender, DataGridSortCommandEventArgs e)
        {
            try
            {
                if (e.SortExpression != string.Empty)
                {
                    MonthlyLaborDistributions.Sort(e.SortExpression);
                    LoadDataGrid();
                }
            }
            catch (Exception ex)
            {
                annunciator.Message = Utility.ExceptionReport.GetExceptionInfo(ex, false);
            }
        }

        /// <summary>
        /// Handler for the event raised when the page is being loaded.
        /// Initialize the bread crumb control, set the page size for the data grid, and load the data grid with data.
        /// If on the first page within the data grid, initalize the pager control.
        /// </summary>
        /// <param name="sender">Control which raised the event</param>
        /// <param name="e">Argument associated with the event</param>
        protected void OnPageLoad(object sender, EventArgs e)
        {
            try
            {
                reportDownload.SQLReportName = "labor_month";
                annunciator.Message = string.Empty;
                annunciator.Title = string.Empty;

                if (header.ModuleName == Constants.Modules.Agreements)
                {
                    personnelSubNavigation.Visible = false;
                }
                else
                {
                    agreementsSubNavigation.Visible = false;
                }

                if (!IsPostBack)
                {
                    ResultsCache.PurgeObject(cachePolicy);

                    //Flush any redundant data from cache
//					laborDistributionGrid.PageSize = 
//						Utility.Settings.GetKeyValue(PersonnelConstants.DataGridPageSizeKey
//						,PersonnelConstants.DefaultDatagridPageSize);

                    breadCrumb.Add("Labor Distribution"
                        , Settings.GetKeyValue
                            ("SubNavigation.Personnel.MonthlyLaborDistributionURL", string.Empty)
                        , PersonnelConstants.DefaultSummaryPageRank);

                    header.ModuleName = Constants.Modules.Personnel;
                    personnelSubNavigation.SelectedLink = PersonnelSubNavigation.laborDistributionCommand;

                    LoadDataGrid();
                }
            }
            catch (Exception ex)
            {
                annunciator.Message = Utility.ExceptionReport.GetExceptionInfo(ex, false);
            }
        }

        #region Search event handler

        /// <summary>
        /// Handler for the event raised by the CommonSearch control when the "Clear Selection" buttion is clicked upon.
        /// The control clears the criretria (specific to this module).
        /// Since in the page life-cycle, the Load occurs before the Clear event, we have to instigate a re-load of the
        /// data grid to refelect the fact that the search criteria has been cleared.
        /// </summary>
        /// <param name="sender">Sender of the event</param>
        /// <param name="e">Argument associated with the event</param>
        protected void OnClearSelection(object sender, CommandEventArgs e)
        {
            CurrentDetailEndDate = DateTime.Today;
            laborDistributionGrid.Visible = false;
            pagerAboveDataGrid.Visible = pagerBelowDataGrid.Visible = false;
        }

        /// <summary>
        /// Handler for the event raised when search is clicked on the search control to load the data.
        /// Please note that since the common search control is contained within a panel, it is more
        /// efficient to wire the handler to the event in the aspx code rather than doing FindControl
        /// in OnInit or InitializeComponent.
        /// </summary>
        /// <param name="args">Argument associated with the event (contains the search criteria dictionary)</param>
        protected void OnSearch(SearchCriteriaArgs args)
        {
            try
            {
                CommonSearchContext searchContext = (CommonSearchContext) cachePolicy.GetCachedObject(CommonSearchContext.CacheKey);
                SearchCriteria searchCriteria = searchContext.GetSearchCriteria(Page.Request.Url.ToString());
                CurrentDetailEndDate = (searchCriteria["PayDateTo"] != null) ? Convert.ToDateTime(searchCriteria["PayDateTo"]) : DateTime.Today;
                LoadDataGrid();
            }
            catch (Exception ex)
            {
                annunciator.Title = "Following error(s) occurred while executing the search";
                annunciator.Message = Utility.ExceptionReport.GetExceptionInfo(ex, false);
            }
        }

        #endregion

        #region Month Paging event handlers

        /// <summary>
        /// Handler for the event raised when the FirstPage link is clicked in the Pager control.
        /// Set the current page index to 0, bind the datagrid with data and manage navigation links.
        /// To avoid superfluous data binding activites, no action is taken if the current page index is already 0.
        /// </summary>
        /// <param name="sender">Control which rasied the event</param>
        /// <param name="e">Arguments associated with the event</param>
        private void OnMonthsFirstPage(object sender, CommandEventArgs e)
        {
            try
            {
                ///set the detail end date to the fiscal year end date of the Monthly Distributions totals Start Date
                DateTime totalsStartDate = MonthlyLaborDistributions.TotalsStartDate;
                CurrentDetailEndDate = new DateTime((totalsStartDate.Month > 9) ? totalsStartDate.AddYears(1).Year : totalsStartDate.Year, 9, 30);
                LoadDataGrid();
            }
            catch (Exception ex)
            {
                annunciator.Message = Utility.ExceptionReport.GetExceptionInfo(ex, false);
            }
        }

        /// <summary>
        /// Handler for the event raised when the LastPage link is clicked in the Pager control.
        /// Set the current page index to one less than the total page count (index is 0-based), bind the datagrid with
        /// data and manage navigation links.
        /// To avoid superfluous data binding activites, no action is taken if the current 
        /// page index is already corresponding to the last page.
        /// </summary>
        /// <param name="sender">Control which rasied the event</param>
        /// <param name="e">Arguments associated with the event</param>
        private void OnMonthsLastPage(object sender, CommandEventArgs e)
        {
            try
            {
                ///set the new detail end date to the Monthly Distributions totals End Date
                CurrentDetailEndDate = (Convert.ToDateTime(MonthlyLaborDistributions.TotalsEndDate.ToShortDateString()) > Convert.ToDateTime(DateTime.Now.ToShortDateString())) ?
                                                                                                                                                                                    MonthlyLaborDistributions.TotalsEndDate : DateTime.Now;
                LoadDataGrid();
            }
            catch (Exception ex)
            {
                annunciator.Message = Utility.ExceptionReport.GetExceptionInfo(ex, false);
            }
        }

        /// <summary>
        /// Handler for the event raised when the NextPage link is clicked in the Pager control.
        /// Increment the current page index, bind the datagrid with data and manage navigation links.
        /// </summary>
        /// <param name="sender">Control which rasied the event</param>
        /// <param name="e">Arguments associated with the event</param>
        private void OnMonthsNextPage(object sender, CommandEventArgs e)
        {
            try
            {
                DateTime newDetailEndDate = MonthlyLaborDistributions.DetailEndDate.AddYears(1);

                CommonSearchContext searchContext = (CommonSearchContext) cachePolicy.GetCachedObject(CommonSearchContext.CacheKey);
                SearchCriteria searchCriteria = searchContext.GetSearchCriteria(Page.Request.Url.ToString());
                if (!string.IsNullOrEmpty(searchCriteria["PayDateTo"]))
                {
                    CurrentDetailEndDate = (newDetailEndDate > MonthlyLaborDistributions.TotalsEndDate) ? MonthlyLaborDistributions.TotalsEndDate : newDetailEndDate;
                }
                else
                {
                    CurrentDetailEndDate = newDetailEndDate; //newDetailEndDate.AddYears(-1);
                }

                LoadDataGrid();
            }
            catch (Exception ex)
            {
                annunciator.Message = Utility.ExceptionReport.GetExceptionInfo(ex, false);
            }
        }

        /// <summary>
        /// Handler for the event raised when the PreviousPage link is clicked in the Pager control.
        /// Decrement the current page index, bind the datagrid with data and manage navigation links.
        /// </summary>
        /// <param name="sender">Control which rasied the event</param>
        /// <param name="e">Arguments associated with the event</param>
        private void OnMonthsPreviousPage(object sender, CommandEventArgs e)
        {
            try
            {
                DateTime newDetailEndDate = MonthlyLaborDistributions.DetailStartDate.AddDays(-1);

                CommonSearchContext searchContext = (CommonSearchContext) cachePolicy.GetCachedObject(CommonSearchContext.CacheKey);
                SearchCriteria searchCriteria = searchContext.GetSearchCriteria(Page.Request.Url.ToString());
                if (!string.IsNullOrEmpty(searchCriteria["PayDateFrom"]))
                {
                    CurrentDetailEndDate = (newDetailEndDate < MonthlyLaborDistributions.TotalsStartDate) ? MonthlyLaborDistributions.TotalsStartDate : newDetailEndDate;
                }
                else
                {
                    CurrentDetailEndDate = newDetailEndDate; //newDetailEndDate.AddYears(-1);
                }
                LoadDataGrid();
            }
            catch (Exception ex)
            {
                annunciator.Message = Utility.ExceptionReport.GetExceptionInfo(ex, false);
            }
        }

        #endregion

        #endregion

        #region Web Form Designer generated code

        protected override void OnInit(EventArgs e)
        {
            cachePolicy = (Policy.ICachePolicy) Session[Policy.Names.CachePolicyKey];
            pageCachePolicy = (Policy.ICachePolicy) Session[Policy.Names.PageCachePolicyKey];

            InitializeComponent();
            base.OnInit(e);

            pagerAboveDataGrid.FirstPage += new CommandEventHandler(this.OnMonthsFirstPage);
            pagerAboveDataGrid.LastPage += new CommandEventHandler(this.OnMonthsLastPage);
            pagerAboveDataGrid.NextPage += new CommandEventHandler(this.OnMonthsNextPage);
            pagerAboveDataGrid.PreviousPage += new CommandEventHandler(this.OnMonthsPreviousPage);

            pagerBelowDataGrid.FirstPage += new CommandEventHandler(this.OnMonthsFirstPage);
            pagerBelowDataGrid.LastPage += new CommandEventHandler(this.OnMonthsLastPage);
            pagerBelowDataGrid.NextPage += new CommandEventHandler(this.OnMonthsNextPage);
            pagerBelowDataGrid.PreviousPage += new CommandEventHandler(this.OnMonthsPreviousPage);

            InsightWebControls.CommonSearch commonSearch = (InsightWebControls.CommonSearch) FindControl("commonSearch");
            commonSearch.ClearSelection += new CommandEventHandler(OnClearSelection);

            this.reportDownload.FailedAction += new System.Web.UI.WebControls.CommandEventHandler(this.OnDownloadFailed);
        }

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.header.Navigate += new System.Web.UI.WebControls.CommandEventHandler(this.OnHeaderNavigate);
            this.personnelSubNavigation.Navigate += new System.Web.UI.WebControls.CommandEventHandler(this.OnSubNavigate);
            this.breadCrumb.Navigate += new System.Web.UI.WebControls.CommandEventHandler(this.OnBreadCrumbNavigate);
            this.laborDistributionGrid.ItemCreated += new System.Web.UI.WebControls.DataGridItemEventHandler(this.OnItemCreated);
            this.laborDistributionGrid.ItemCommand += new System.Web.UI.WebControls.DataGridCommandEventHandler(this.OnItemCommand);
            this.laborDistributionGrid.SortCommand += new System.Web.UI.WebControls.DataGridSortCommandEventHandler(this.OnSort);
            this.laborDistributionGrid.ItemDataBound += new System.Web.UI.WebControls.DataGridItemEventHandler(this.OnItemDataBound);
            this.ID = "MonthlyLaborDistribution";
            this.Load += new System.EventHandler(this.OnPageLoad);
        }

        #endregion

        #region Private Methods

        /// <summary>
        /// Adds refresh dates currently visible on the page to the search criteria string
        /// to be passed down to reports. The criteria does not persist to the SearchCriteria
        /// object.
        /// </summary>
        /// <param name="searchCriteria">Object containing search criteria.</param>
        /// <returns>A string representation of search criteria. </returns>
        private string AddRefreshDatesToCriteria(SearchCriteria searchCriteria)
        {
            StringBuilder criteria = new StringBuilder(searchCriteria.ToString(";"));
            if (refreshDates.SalaryAsOfDateVisible)
            {
                criteria.AppendFormat("Last Salary Post|{0};", refreshDates.SalaryAsOfDate.ToShortDateString());
            }
            if (refreshDates.GLAsOfDateVisible)
            {
                criteria.AppendFormat("Last GL Post|{0};", refreshDates.GLPostAsOfDate.ToShortDateString());
            }
            if (refreshDates.POAPAsOfDateVisible)
            {
                criteria.AppendFormat("Last PO/AP Post|{0};", refreshDates.POAPAsOfDate.ToShortDateString());
            }
            return criteria.ToString();
        }

        /// <summary>
        /// Load the datagrid with sufficient data for display within one page of the data grid. This is done as follows:
        /// Get the distribution for all personnel that the user has access to. Use that to initialize the data grid and
        /// the pager controls based on the page size of the data grid.
        /// The pagers are made visible only when more than one page of data can be displayed.
        /// If there is no data to display, warn the user via the annunciator.
        /// </summary>
        private void LoadDataGrid()
        {
            MonthlyLaborDistributions monthlyLaborDistributions = MonthlyLaborDistributions;

            //set the text on the pagercontrols
            pagerBelowDataGrid.LeftText = pagerAboveDataGrid.LeftText =
                String.Format("{0}&nbsp;Personnel", MonthlyLaborDistributions.Count);

            DateTime currentDetailEndDate = CurrentDetailEndDate;
            DateTime fiscalEndDate = new DateTime((currentDetailEndDate.Month > 9) ? currentDetailEndDate.AddYears(1).Year : currentDetailEndDate.Year, 9, 30);

            pagerBelowDataGrid.RightText = pagerAboveDataGrid.RightText =
                String.Format("Fiscal&nbsp;Year&nbsp;{0}",
                    fiscalEndDate.Year);

            laborDistributionGrid.DataSource = monthlyLaborDistributions.GetDataContainer().Tables[monthlyLaborDistributions.CurrentDataTableName];
            laborDistributionGrid.DataBind();

            ManagePagination();

            if (!laborDistributionGrid.Visible)
            {
                annunciator.Message = "No labor distribution data found for user";
            }
        }

        /// <summary>
        /// Manages the pagination logic.
        /// Set the First record and last record values for the pager controls
        /// based on the current page index and the data grid page size respectively
        /// </summary>
        private void ManagePagination()
        {
            laborDistributionGrid.Visible = pagerAboveDataGrid.Visible = pagerBelowDataGrid.Visible =
                (laborDistributionGrid.Items.Count > 0);
            if (laborDistributionGrid.Visible)
            {
                CommonSearchContext searchContext = (CommonSearchContext) cachePolicy.GetCachedObject(CommonSearchContext.CacheKey);
                SearchCriteria searchCriteria = searchContext.GetSearchCriteria(Page.Request.Url.ToString());

                bool isEnabled = false;
                if (!string.IsNullOrEmpty(searchCriteria["PayDateFrom"]))
                {
                    isEnabled = MonthlyLaborDistributions.DetailStartDate > MonthlyLaborDistributions.TotalsStartDate;
                }

                pagerBelowDataGrid.EnableFirstPage = pagerAboveDataGrid.EnableFirstPage = isEnabled;

                isEnabled = true;
                if (!string.IsNullOrEmpty(searchCriteria["PayDateFrom"]))
                {
                    isEnabled = MonthlyLaborDistributions.DetailStartDate > MonthlyLaborDistributions.TotalsStartDate;
                }

                pagerBelowDataGrid.EnablePreviousPage = pagerAboveDataGrid.EnablePreviousPage = isEnabled;

                //Enable Next and Last links on the pager if 
                //1.  CurrentDetailEndDate < the specified totals "To" date 
                //or
                //2.  CurrentDetailEndDate < Today and the Totals "To" date was not specified
                if (!string.IsNullOrEmpty(searchCriteria["PayDateTo"]))
                {
                    pagerBelowDataGrid.EnableLastPage = pagerBelowDataGrid.EnableNextPage =
                        pagerAboveDataGrid.EnableLastPage = pagerAboveDataGrid.EnableNextPage =
                            CurrentDetailEndDate < MonthlyLaborDistributions.TotalsEndDate;
                }
                else
                {
                    pagerBelowDataGrid.EnableLastPage = pagerBelowDataGrid.EnableNextPage =
                        pagerAboveDataGrid.EnableLastPage = pagerAboveDataGrid.EnableNextPage =
                            CurrentDetailEndDate < DateTime.Today;
                }
            }
        }

        #endregion

        private void OnHeaderNavigate(object sender, CommandEventArgs e)
        {
            PurgeCache();
        }

        private void OnSubNavigate(object sender, CommandEventArgs e)
        {
            PurgeCache();
        }

        private void OnBreadCrumbNavigate(object sender, CommandEventArgs e)
        {
            PurgeCache();
        }

        /// <summary>
        /// Invoked by the download bar when it catches an exception.
        /// </summary>
        /// <param name="sender">Control which raised the event</param>
        /// <param name="e">Argument associated with the event</param>
        private void OnDownloadFailed(object sender, CommandEventArgs e)
        {
            annunciator.Title = "Following error(s) occurred while downloading";
            annunciator.Message = Utility.ExceptionReport.GetExceptionInfo((Exception) e.CommandArgument, false);
        }

        public void PurgeCache()
        {
            ResultsCache.PurgeObject(cachePolicy);
        }
    }
}